# -*- conding:utf-8 -*-
"""
@author:ym
@time:06-2022/6/4-
Copyright (c) All Rights Reserved, 2022/6/4.
"""
from algorithm.newConstrainsAlgorithm import ConstrainsAlgorithm
from algorithm.newNoConstrainsAlgorithm import NoConstrainsAlgorithm
from algorithm.randomGraphRequest import randomGR
import json

from flask import Flask, jsonify, Response
from flask_cors import CORS
# 这里使用别名，因为和算法中某个变量命名冲突
from flask import request as flask_request

app = Flask(__name__)
# 注册CORS, "/*" 允许访问所有api
CORS(app, resources=r'/*')



@app.route("/api/getRequest",methods=["GET","POST"])
def getRequest():
    try:
        N = flask_request.json['nodeNum']
        # N = 50
        # function_V_num为服务器结点,默认值即可
        N = int(N)
        function_V_num = N // 10
        # p为结点间连线的概率，默认值即可,连线概率
        p = 3 / N
        # max_E_cost为最大的边权值,默认值即可
        max_E_cost = flask_request.json['maxEdgeCost']
        # max_E_cost = 10
        # 功能数,就默认值即可
        function_num = flask_request.json['functionNum']
        # function_num = 5
        # 最大包大小，默认值 5
        max_bk = flask_request.json['maxBk']
        # 最大功能消耗，默认值
        max_deployment_cost = flask_request.json['maxDeployMent']
        # max_deployment_cost = 5
        # 并行功能数，默认值
        parallel_num = flask_request.json['parallelNum']
        # parallel_num = 3
        # 目的结点占比，默认值
        destination_V_radio = flask_request.json['destinationVRadio']
        # destination_V_radio = 0.1
        # 并行功能起始位置，默认0
        parallel_position = flask_request.json['parallelPostion']
        # parallel_position = 0
        rGR = randomGR()
        """
        返回值介绍
        initial_Graph是一个MGraph类的实例，里面的图矩阵和结点就是我们要显示的拓扑图数据结构。边为inf的就是无连边权值无限大，在图中inf的边不展示
        function_V是服务器结点，在拓扑图中这种结点可以用其他颜色表示。如果太麻烦就算了
        E_constrains, function_V_constrains 是边和结点资源限制，不用展示。但在计算算法时要用到
        neibor_function_v 算法计算要用到，不用展示
        """
        initial_Graph, function_V, E_constrains, function_V_constrains, neibor_function_v = rGR.random_initial_Graph(N,
                                                                                                                     function_V_num,
                                                                                                                     p,
                                                                                                                     max_E_cost)
        # 初始化图，
        graph = {'graph_V': initial_Graph.V, 'graph_E': initial_Graph.E.tolist()}
        request = rGR.random_request(N, function_num, function_V_num, max_bk, max_deployment_cost, parallel_num,
                                     function_V,
                                     destination_V_radio, neibor_function_v, initial_Graph, parallel_position)
        deployment_cost = request['deployment_cost']
        deployment_cost = deployment_cost.tolist()
        request['deployment_cost'] = deployment_cost
        ret_Json = {
            "graph": graph,  # 这里是显示的图表相关的信息
            "request": request,
            "functionV": function_V,  # 服务器节点，特殊显示
        }
        ret_data = {
            "status": 200,
            "data": ret_Json
        }
        header = {
            "Access-Control-Allow-Credentials": "true"
        }

    except Exception as e:
        ret_data = {
            "status": 500,
            "data": str(e)
        }
        header = {
            "Access-Control-Allow-Credentials": "true"
        }
    return Response(json.dumps(ret_data), mimetype='application/json', headers=header)

# MBPE算法请求
@app.route('/api/BMPE', methods=['POST'])
def mbpe_result():
    """
    算法一接口
    :param
    nodeNum: 节点数->N
    functionVNum: 服务器节点： 默认是N/10 -> function_V_num
    functionNum: 功能数 ->function_num
    maxBk: 最大包数 ->max_bk
    maxEdgeCost: 最大边权值->max_E_cost
    maxDeployMent: 最大功能消耗——>max_deployment_cost
    parallelNum: 并行功能数->parallel_num
    destinationVRadio: 目的结点占比，默认值 0.1  ->destination_V_radio
    parallelPostion: 并行功能起始位置 默认0 ->parallel_position
    :return:
    """
    # temp = request.form
    ret_data={}
    header = {}
    # print(temp)
    try:
        N = flask_request.json['nodeNum']
        # N = 50
        # function_V_num为服务器结点,默认值即可
        N = int(N)
        function_V_num = int(N) // 10
        # p为结点间连线的概率，默认值即可,连线概率
        p = 3 / int(N)
        # max_E_cost为最大的边权值,默认值即可
        max_E_cost = flask_request.json['maxEdgeCost']
        # max_E_cost = 10
        # 功能数,就默认值即可
        function_num = flask_request.json['functionNum']
        # function_num = 5
        # 最大包大小，默认值 5
        max_bk = flask_request.json['maxBk']
        # 最大功能消耗，默认值
        max_deployment_cost = flask_request.json['maxDeployMent']
        # max_deployment_cost = 5
        # 并行功能数，默认值
        parallel_num = flask_request.json['parallelNum']
        # parallel_num = 3
        # 目的结点占比，默认值
        destination_V_radio = flask_request.json['destinationVRadio']
        # destination_V_radio = 0.1
        # 并行功能起始位置，默认0
        parallel_position = flask_request.json['parallelPostion']
        # parallel_position = 0
        rGR = randomGR()
        """
        返回值介绍
        initial_Graph是一个MGraph类的实例，里面的图矩阵和结点就是我们要显示的拓扑图数据结构。边为inf的就是无连边权值无限大，在图中inf的边不展示
        function_V是服务器结点，在拓扑图中这种结点可以用其他颜色表示。如果太麻烦就算了
        E_constrains, function_V_constrains 是边和结点资源限制，不用展示。但在计算算法时要用到
        neibor_function_v 算法计算要用到，不用展示
        """
        initial_Graph, function_V, E_constrains, function_V_constrains, neibor_function_v = rGR.random_initial_Graph(N,
                                                                                                                     function_V_num,
                                                                                                                     p,
                                                                                                                     max_E_cost)

        # 初始化图，
        graph = {'graph_V': initial_Graph.V, 'graph_E': initial_Graph.E.tolist()}
        request = rGR.random_request(N, function_num, function_V_num, max_bk, max_deployment_cost, parallel_num,
                                     function_V,
                                     destination_V_radio, neibor_function_v, initial_Graph, parallel_position)
        deployment_cost = request['deployment_cost']
        deployment_cost = deployment_cost.tolist()
        request['deployment_cost'] = deployment_cost

        # 两个展示的。一个是图一个是请求
        NCA = NoConstrainsAlgorithm()
        Tmatrix, Ttable, weightsum, SFC, T = NCA.noContraintTackleRequest(request, parallel_num, initial_Graph, function_V)

        """weightsum为总权值，resultTree就是计算出来的树，deployNode是功能部署位置（对应服务器结点），deployServer对应部署的功能"""
        NCA_result = {'weightsum': weightsum, 'resultTree': T.tolist(), 'deployNode': SFC['deploy_Node'],
                      'deployServer': SFC['deploy_server']}
        ret_Json = {
            "graph": graph,  # 这里是显示的图表相关的信息
            "request": request,
            "functionV": function_V,  # 服务器节点，特殊显示
            "ncaResult": NCA_result,
        }
        ret_data = {
            "status": 200,
            "data": ret_Json
        }
        header={
            "Access-Control-Allow-Credentials": "true"
        }
    except Exception as e:
        ret_data = {
            "status": 500,
            "data": str(e)
        }
        header = {
            "Access-Control-Allow-Credentials": "true"
        }
    # ret_Json
    return Response(json.dumps(ret_data), mimetype='application/json', headers=header)


@app.route('/api/CA', methods=['POST'])
def ca_result():
    """
    算法二
        :param
        nodeNum: 节点数->N
        functionVNum: 服务器节点： 默认是N/10 -> function_V_num
        functionNum: 功能数 ->function_num
        maxBk: 最大包数 ->max_bk
        maxEdgeCost: 最大边权值->max_E_cost
        maxDeployMent: 最大功能消耗——>max_deployment_cost
        parallelNum: 并行功能数->parallel_num
        destinationVRadio: 目的结点占比，默认值 0.1  ->destination_V_radio
        parallelPostion: 并行功能起始位置 默认0 ->parallel_position
        :return:
        """
    # temp = request.form

    # print(temp)
    # try:
    # N为结点数目，应由程序传入
    ret_data = {}
    header = {}
    try:
        N = flask_request.json['nodeNum']
        # N = 50
        # function_V_num为服务器结点,默认值即可
        N = int(N)
        function_V_num = N // 10
        # p为结点间连线的概率，默认值即可,连线概率
        p = 3 / N
        # max_E_cost为最大的边权值,默认值即可
        max_E_cost = flask_request.json['maxEdgeCost']
        # max_E_cost = 10
        # 功能数,就默认值即可
        function_num = flask_request.json['functionNum']
        # function_num = 5
        # 最大包大小，默认值 5
        max_bk = flask_request.json['maxBk']
        # 最大功能消耗，默认值
        max_deployment_cost = flask_request.json['maxDeployMent']
        # max_deployment_cost = 5
        # 并行功能数，默认值
        parallel_num = flask_request.json['parallelNum']
        # parallel_num = 3
        # 目的结点占比，默认值
        destination_V_radio = flask_request.json['destinationVRadio']
        # destination_V_radio = 0.1
        # 并行功能起始位置，默认0
        parallel_position = flask_request.json['parallelPostion']
        # parallel_position = 0
        rGR = randomGR()
        """
        返回值介绍
        initial_Graph是一个MGraph类的实例，里面的图矩阵和结点就是我们要显示的拓扑图数据结构。边为inf的就是无连边权值无限大，在图中inf的边不展示
        function_V是服务器结点，在拓扑图中这种结点可以用其他颜色表示。如果太麻烦就算了
        E_constrains, function_V_constrains 是边和结点资源限制，不用展示。但在计算算法时要用到
        neibor_function_v 算法计算要用到，不用展示
        """
        initial_Graph, function_V, E_constrains, function_V_constrains, neibor_function_v = rGR.random_initial_Graph(N,
                                                                                                                     function_V_num,
                                                                                                                     p,
                                                                                                                     max_E_cost)
        # 初始化图，
        graph = {'graph_V': initial_Graph.V, 'graph_E': initial_Graph.E.tolist()}
        request = rGR.random_request(N, function_num, function_V_num, max_bk, max_deployment_cost, parallel_num,
                                     function_V,
                                     destination_V_radio, neibor_function_v, initial_Graph, parallel_position)
        deployment_cost = request['deployment_cost']
        deployment_cost = deployment_cost.tolist()
        request['deployment_cost'] = deployment_cost

        # 两个展示的。一个是图一个是请求
        CA = ConstrainsAlgorithm()
        Tmatrix, Ttable, weightsum, SFC, T = CA.ContraintTackleRequest(request, initial_Graph, function_V, E_constrains,
                                                                       function_V_constrains)

        # CA_result = {'weightsum': weightsum, 'SFC': SFC}
        CA_result = {'weightsum': weightsum, 'resultTree': T.tolist(), 'deployNode': SFC['deploy_Node'],
                     'deployServer': SFC['deploy_server']}


        ret_Json = {
            "graph": graph,  # 这里是显示的图表相关的信息
            "request": request,
            "functionV": function_V,  # 服务器节点，特殊显示
            "ncaResult": CA_result,
        }
        ret_data = {
            "status": 200,
            "data": ret_Json
        }
        header = {
            "Access-Control-Allow-Credentials": "true"
        }
    except Exception as e:
        ret_data = {
            "status": 500,
            "data": str(e)
        }
        header = {
            "Access-Control-Allow-Credentials": "true"
        }
    # ret_Json
    return Response(json.dumps(ret_data), mimetype='application/json', headers=header)


# 暂时本地使用，后续部署到服务器
# app.run(host='127.0.0.1', port=5000, debug=True)
# 服务器部署，使用nginx反向代理
app.run(host='0.0.0.0', port=5000, debug=True)
